home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / 3DDEMO.ZIP / 3D / SOURCE / BMAPGFX.CPP < prev    next >
C/C++ Source or Header  |  1996-07-21  |  13KB  |  480 lines

  1. #include "bmapgfx.hpp"
  2.  
  3. // Copyright (c) 1996 by Kerrigan Burgess, all rights reserved.
  4.  
  5. BITMAPGFXCLASS::BITMAPGFXCLASS(void)         // constructor.
  6. {
  7.   Image=NULL;
  8. }
  9.  
  10. BITMAPGFXCLASS::~BITMAPGFXCLASS(void)         // destructor.
  11. {    
  12.   if (Image != NULL)
  13.     delete Image;  
  14. }
  15.  
  16. void BITMAPGFXCLASS::Create( ImageStats *Stats, unsigned char *bitmap )
  17. {
  18.    if (Image != NULL)
  19.      delete Image;
  20.    Image = new unsigned char [ Stats->size ];
  21.    if (Image==NULL)
  22.      Error("Not enough memory\n");
  23.  
  24.    Image = bitmap;
  25.  
  26.    MidX = Stats->width/2;
  27.    MidY = Stats->height/2;
  28.    
  29.    Coords[0].x = 0-MidX;
  30.    Coords[0].y = 0-MidY;
  31.    Coords[1].x = 0-MidX;
  32.    Coords[1].y = (Stats->height)-MidY;
  33.    Coords[2].x = (Stats->width)-MidX;
  34.    Coords[2].y = (Stats->height)-MidY;
  35.    Coords[3].x = (Stats->width)-MidX;
  36.    Coords[3].y = 0-MidY;
  37.  
  38.    Coords[0].u = 1;
  39.    Coords[0].v = 1;
  40.    Coords[1].u = 1;
  41.    Coords[1].v = Stats->height-1;
  42.    Coords[2].u = Stats->width-1;
  43.    Coords[2].v = Stats->height-1;
  44.    Coords[3].u = Stats->width-1;
  45.    Coords[3].v = 1;
  46. }
  47.  
  48. void BITMAPGFXCLASS::Scale(unsigned char *Buffer, float percentage)
  49. {
  50.   int x0,y0,x2,y2;
  51.  
  52.   x0 = Coords[0].x*percentage + HALF_SCREEN_WIDTH;
  53.   y0 = Coords[0].y*percentage + HALF_SCREEN_HEIGHT;
  54.   x2 = Coords[2].x*percentage + HALF_SCREEN_WIDTH;
  55.   y2 = Coords[2].y*percentage + HALF_SCREEN_HEIGHT;
  56.  
  57.   ScaleBitMap(x0,y0,x2,y2,
  58.               Coords[0].u,Coords[0].v,Coords[2].u,Coords[2].v,
  59.                 Buffer,Image);
  60. }
  61.  
  62. void BITMAPGFXCLASS::ScaleBitMap(int x0,int y0,int x2,int y2,
  63.                                  int u0,int v0,int u2,int v2,
  64.                                  unsigned char *Buffer,unsigned char *Image)
  65. {
  66.   unsigned char *Source,*Dest;
  67.   long LeftU,u,v,Du,Dv;
  68.   int x,y,vint;
  69.  
  70.     // This is hard coded for 320x200.
  71.     
  72.     Du     = ((u2-u0)<<16)/(x2-x0);       // point 16 format.
  73.     Dv     = ((v2-v0)<<16)/(y2-y0);
  74.     LeftU  = u0<<16;
  75.     v      = v0<<16;
  76.  
  77.     if (y0 < _MinClipY)
  78.     {
  79.        v  = v + (_MinClipY - y0)*Dv;
  80.        y0 = _MinClipY;
  81.     }
  82.                 
  83.     if (y2 > _MaxClipY)
  84.       y2    = _MaxClipY;
  85.  
  86.     if (x0 < _MinClipX)
  87.     {
  88.        LeftU = LeftU + (_MinClipX - x0)*Du;
  89.        x0    = _MinClipX;
  90.     }
  91.  
  92.     if (x2 > _MaxClipX)
  93.        x2    = _MaxClipX;
  94.      
  95.     Buffer+=x0+(y0<<8)+(y0<<6);
  96.  
  97.    for (y=y0;y<y2;y++)
  98.    {
  99.        u=LeftU;
  100.        vint=v>>16;
  101.        Source=Image+(vint<<8)+(vint<<6);
  102.        Dest=Buffer;
  103.        for (x=x0;x<x2;x++)
  104.        {
  105.        *Dest++=Source[ u>>16 ];
  106.        u+=Du;
  107.        }
  108.        v+=Dv;
  109.        Buffer+=SCREENWIDTH;            
  110.    }
  111. }
  112.  
  113. void BITMAPGFXCLASS::Rotate( unsigned char *Buffer, double angle, float scale)
  114. {
  115.   float Cos, Sin, CosScale, CosAspectScale, SinAspect;
  116.   static double ang=0;
  117.   int x0,y0,x1,y1,x2,y2,x3,y3;
  118.   int u0,v0,u1,v1,u2,v2,u3,v3;
  119.  
  120.   ang+=angle;
  121.  
  122.   angle = -ang*DEGREES_TO_RADIANS;         
  123.   Sin = (float)sin ( angle );
  124.   Cos = (float)cos ( angle );
  125.   
  126.   x0 = Coords[0].x*Cos - Coords[0].y*Sin;
  127.   y0 = Coords[0].x*Sin + Coords[0].y*Cos;
  128.   x1 = Coords[1].x*Cos - Coords[1].y*Sin;
  129.   y1 = Coords[1].x*Sin + Coords[1].y*Cos;
  130.   x2 = Coords[2].x*Cos - Coords[2].y*Sin;
  131.   y2 = Coords[2].x*Sin + Coords[2].y*Cos;
  132.   x3 = Coords[3].x*Cos - Coords[3].y*Sin;
  133.   y3 = Coords[3].x*Sin + Coords[3].y*Cos;
  134.  
  135.   x0=x0*scale+HALF_SCREEN_WIDTH;
  136.   y0=y0*scale+HALF_SCREEN_HEIGHT;
  137.   x1=x1*scale+HALF_SCREEN_WIDTH;
  138.   y1=y1*scale+HALF_SCREEN_HEIGHT;
  139.   x2=x2*scale+HALF_SCREEN_WIDTH;
  140.   y2=y2*scale+HALF_SCREEN_HEIGHT;
  141.   x3=x3*scale+HALF_SCREEN_WIDTH;
  142.   y3=y3*scale+HALF_SCREEN_HEIGHT;
  143.   
  144.   u0=Coords[0].u;
  145.   v0=Coords[0].v;
  146.   u1=Coords[1].u;
  147.   v1=Coords[1].v;
  148.   u2=Coords[2].u;
  149.   v2=Coords[2].v;
  150.   u3=Coords[3].u;
  151.   v3=Coords[3].v;
  152.  
  153.   RotateBitMap( x0,y0,x1,y1,x2,y2,
  154.                 u0,v0,u1,v1,u2,v2,
  155.              Buffer, Image);
  156.  
  157.   RotateBitMap( x0,y0,x2,y2,x3,y3,
  158.                 u0,v0,u2,v2,u3,v3,
  159.              Buffer, Image);
  160. }
  161.  
  162. void BITMAPGFXCLASS::RotateBitMap(int x0,int y0,int x1,int y1,int x2,int y2,
  163.                                   int u0,int v0,int u1,int v1,int u2,int v2,
  164.                                  unsigned char *Buffer,unsigned char *Image)
  165. {
  166.   long width, height,slope;
  167.   long u,v,ScanU,ScanV,LeftU,LeftV,LeftDu,LeftDv;
  168.   long LeftX,RightX,LeftDx,RightDx;
  169.   long ClipLeftX,ClipRightX;
  170.   int vint,x,y,newx,newu,newv,tempx,tempy,tempu,tempv,ydiff;
  171.   int oldx2,oldy2,oldu2,oldv2;
  172.   int GENERAL;
  173.   unsigned char *Start;
  174.  
  175.     if (y1<y0)              // switch. They're in the wrong order.
  176.     {
  177.         tempx=x0; tempy=y0;
  178.         x0=x1;    y0=y1;
  179.         x1=tempx; y1=tempy;
  180.  
  181.         tempu=u0; tempv=v0;
  182.         u0=u1;    v0=v1;
  183.         u1=tempu; v1=tempv;
  184.     }    
  185.     if (y2<y0)              // switch. They're in the wrong order.
  186.     {
  187.         tempx=x0; tempy=y0;
  188.         x0=x2;    y0=y2;
  189.         x2=tempx; y2=tempy;
  190.  
  191.         tempu=u0; tempv=v0;
  192.         u0=u2;    v0=v2;
  193.         u2=tempu; v2=tempv;
  194.     }
  195.     if (y2<y1)              // switch. They're in the wrong order.
  196.     {
  197.         tempx=x1; tempy=y1;
  198.         x1=x2;    y1=y2;
  199.         x2=tempx; y2=tempy;
  200.  
  201.         tempu=u1; tempv=v1;
  202.         u1=u2;    v1=v2;
  203.         u2=tempu; v2=tempv;
  204.     }    
  205.  
  206.     GENERAL=FALSE;          // reset cases (for Triangle).
  207.     Start=Buffer;           // save starting point of Buffer.
  208.     
  209.     if (y0==y1)
  210.       goto FLAT_TOP;
  211.     if (y1==y2)
  212.       goto FLAT_BOTTOM;
  213.     else
  214.       GENERAL=TRUE;
  215.          
  216.     height = 65536/(y2-y0);
  217.     slope = (x2-x0)*height;               
  218.     newx  = x0+( (slope*(y1-y0))>>16 );
  219.     newu  = (((y1-y0)*u2+(y2-y1)*u0)*height)>>16;
  220.     newv  = (((y1-y0)*v2+(y2-y1)*v0)*height)>>16;
  221.  
  222.     oldx2 = x2;                            // save values for later.
  223.     oldy2 = y2;
  224.     oldu2 = u2;
  225.     oldv2 = v2;
  226.     
  227.     x2    = newx;
  228.     y2    = y1;           
  229.     u2    = newu;
  230.     v2    = newv;
  231.     
  232.     FLAT_BOTTOM:
  233.         
  234.     if (x2<x1)
  235.     {
  236.       tempx=x2; x2=x1; x1=tempx;
  237.       tempu=u2; u2=u1; u1=tempu;
  238.       tempv=v2; v2=v1; v1=tempv;
  239.     }
  240.  
  241.     height  = 65536/(y2-y0);              // fixed point 16.
  242.     width   = 65536/(x2-x1+1);
  243.     LeftDx  = (x1-x0)*height;              
  244.     RightDx = (x2-x0)*height;
  245.     LeftDu  = (u1-u0)*height;
  246.     LeftDv  = (v1-v0)*height;
  247.  
  248.     LeftX   = x0<<16;
  249.     RightX  = LeftX + 32768;                      // 32768 is 0.5 fixed point 16
  250.     LeftU   = u0<<16;
  251.     LeftV   = v0<<16;
  252.  
  253.     ScanU = (u2-u1)*width;         // constant across whole triangle.
  254.     ScanV = (v2-v1)*width;
  255.  
  256.     if (y0 < _MinClipY)
  257.     {
  258.        ydiff  = _MinClipY - y0;
  259.        LeftX  = LeftX+LeftDx*ydiff;
  260.        RightX = RightX+RightDx*ydiff;
  261.  
  262.        LeftU  = LeftU+LeftDu*ydiff;
  263.        LeftV  = LeftV+LeftDv*ydiff;
  264.  
  265.            y0 = _MinClipY;
  266.     }
  267.                 
  268.     if (y2 > _MaxClipY)
  269.       y2 = _MaxClipY;
  270.              
  271.     Buffer+=(y0<<8)+(y0<<6);
  272.  
  273.     if (x0>=_MinClipX && x0<=_MaxClipX &&
  274.         x1>=_MinClipX && x1<=_MaxClipX &&
  275.         x2>=_MinClipX && x2<=_MaxClipX)
  276.     {                   
  277.        for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)    
  278.        {
  279.           u=LeftU;
  280.           v=LeftV;
  281.           for (x=( LeftX>>16 );x<=( RightX>>16 );x++)
  282.           {                 
  283.              vint=v>>16;
  284.              Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
  285.              u+=ScanU;
  286.              v+=ScanV;
  287.           }       
  288.           LeftX  += LeftDx;
  289.           RightX += RightDx;
  290.           LeftU  += LeftDu;
  291.           LeftV  += LeftDv;
  292.        }
  293.     }
  294.     else
  295.     {
  296.        for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)    
  297.        {
  298.           ClipLeftX  = LeftX>>16;
  299.           ClipRightX = RightX>>16;
  300.  
  301.           u=LeftU;
  302.           v=LeftV;
  303.  
  304.           if (ClipLeftX < _MinClipX)
  305.           {
  306.             if (ClipRightX < _MinClipX)
  307.         {
  308.                LeftX  += LeftDx;      // update the intensities and slopes.
  309.                RightX += RightDx;     // before continuing.
  310.                LeftU  += LeftDu;
  311.                LeftV  += LeftDv;
  312.                continue;
  313.         }
  314.             u         = LeftU + (_MinClipX - ClipLeftX)*ScanU;
  315.             v         = LeftV + (_MinClipX - ClipLeftX)*ScanV;
  316.             ClipLeftX = _MinClipX;     // the clipped amount.
  317.           }
  318.  
  319.           if (ClipRightX > _MaxClipX)
  320.           {
  321.             if (ClipLeftX > _MaxClipX)
  322.         {
  323.                LeftX  += LeftDx;      // update the intensities and slopes.
  324.                RightX += RightDx;     // before continuing.
  325.                LeftU  += LeftDu;
  326.                LeftV  += LeftDv;
  327.                continue;
  328.         }
  329.             ClipRightX = _MaxClipX;
  330.           }
  331.                                             
  332.           for (x=ClipLeftX;x<=ClipRightX;x++)
  333.           {
  334.              vint=v>>16;
  335.              Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
  336.              u+=ScanU;
  337.              v+=ScanV;
  338.           }               
  339.           LeftX  += LeftDx;
  340.           RightX += RightDx;
  341.           LeftU  += LeftDu;
  342.           LeftV  += LeftDv;
  343.        }
  344.     }
  345.  
  346.     if (!GENERAL)
  347.       return;
  348.  
  349.     x0     = x1;                 // setup for FLAT_TOP.
  350.     y0     = y1;
  351.     u0     = u1;
  352.     v0     = v1;
  353.  
  354.     x1     = x2;
  355.     u1     = u2;
  356.     v1     = v2;
  357.  
  358.     x2     = oldx2;
  359.     y2     = oldy2;
  360.     u2     = oldu2;
  361.     v2     = oldv2;
  362.     
  363.     Buffer = Start;          // reset Buffer to starting point.
  364.  
  365.     FLAT_TOP: 
  366.  
  367.     if (x1<x0)
  368.     {
  369.       tempx=x1; x1=x0; x0=tempx;
  370.       tempu=u1; u1=u0; u0=tempu;
  371.       tempv=v1; v1=v0; v0=tempv;
  372.     }
  373.  
  374.     height    = 65536/(y2-y0);     // fixed point 16.
  375.     width     = 65536/(x1-x0+1);
  376.     
  377.     LeftDx    = (x2-x0)*height;    // Inverse left and right slope.
  378.     RightDx   = (x2-x1)*height;
  379.     LeftDu    = (u2-u0)*height;
  380.     LeftDv    = (v2-v0)*height;
  381.  
  382.     LeftX     = x0<<16;
  383.     RightX    = (x1<<16)+32768;        // 32768 is 0.5 fixed point 16.
  384.     LeftU     = u0<<16;
  385.     LeftV     = v0<<16;
  386.  
  387.     ScanU     = (u1-u0)*width;
  388.     ScanV     = (v1-v0)*width;
  389.                      
  390.     if (y0 < _MinClipY)
  391.     {
  392.        ydiff  = _MinClipY - y0;   
  393.        LeftX  = LeftX+LeftDx*ydiff;
  394.        RightX = RightX+RightDx*ydiff;
  395.  
  396.        LeftU  = LeftU+LeftDu*ydiff;
  397.        LeftV  = LeftV+LeftDv*ydiff;
  398.  
  399.            y0 = _MinClipY;
  400.     }
  401.                 
  402.     if (y2 > _MaxClipY)
  403.       y2 = _MaxClipY;
  404.               
  405.     Buffer+=(y0<<8)+(y0<<6);
  406.  
  407.     if (x0>=_MinClipX && x0<=_MaxClipX &&
  408.         x1>=_MinClipX && x1<=_MaxClipX &&
  409.         x2>=_MinClipX && x2<=_MaxClipX)
  410.     {                   
  411.        for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)    
  412.        {        
  413.           u=LeftU;
  414.           v=LeftV;
  415.           for (x=( LeftX>>16 );x<=( RightX>>16 );x++)
  416.           {                 
  417.              vint=v>>16;
  418.              Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
  419.              u+=ScanU;
  420.              v+=ScanV;
  421.           }
  422.           LeftX  += LeftDx;
  423.           RightX += RightDx;
  424.           LeftU  += LeftDu;
  425.           LeftV  += LeftDv;
  426.        }
  427.     }
  428.     else
  429.     {
  430.        for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)    
  431.        {
  432.           ClipLeftX  = ( LeftX>>16 );
  433.           ClipRightX = ( RightX>>16 );
  434.  
  435.           u=LeftU;
  436.           v=LeftV;
  437.  
  438.           if (ClipLeftX < _MinClipX)
  439.           {
  440.             if (ClipRightX < _MinClipX)
  441.         {
  442.                LeftX  += LeftDx;      // update the intensities and slopes.
  443.                RightX += RightDx;     // before continuing.
  444.                LeftU  += LeftDu;
  445.                LeftV  += LeftDv;
  446.                continue;
  447.         }
  448.             u          = LeftU + (_MinClipX - ClipLeftX)*ScanU;
  449.             v          = LeftV + (_MinClipX - ClipLeftX)*ScanV;
  450.             ClipLeftX  = _MinClipX;   // the clipped amount.
  451.           }
  452.  
  453.           if (ClipRightX > _MaxClipX)
  454.           {
  455.             if (ClipLeftX > _MaxClipX)
  456.         {
  457.                LeftX  += LeftDx;      // update the intensities and slopes.
  458.                RightX += RightDx;     // before continuing.
  459.                LeftU  += LeftDu;
  460.                LeftV  += LeftDv;
  461.                continue;
  462.         }
  463.             ClipRightX = _MaxClipX;
  464.           }
  465.                                             
  466.           for (x=ClipLeftX;x<=ClipRightX;x++)
  467.           {
  468.              vint=(v>>16);
  469.              Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
  470.              u+=ScanU;
  471.              v+=ScanV;
  472.           }               
  473.           LeftX  += LeftDx;
  474.           RightX += RightDx;
  475.           LeftU  += LeftDu;
  476.           LeftV  += LeftDv;
  477.        }
  478.     }
  479. }
  480.